package gdt.dao.jpa;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import gdt.dao.GenericDAO;

public class JPAGenericDAO<T,ID extends Serializable> implements GenericDAO<T, ID>{

	private EntityManager entityManager;
	
	@PersistenceContext
	public void setEntityManager(EntityManager em) {
		this.entityManager = em;
	}
	
	public EntityManager getEntityManager() {
		if (entityManager == null)
            throw new IllegalStateException("EntityManager has not been set on DAO before usage");
		return entityManager;
	}
	
	protected Class<T> entityClass;
    
    @SuppressWarnings("unchecked")
	public JPAGenericDAO() {
    	this.entityClass = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
    }

	public Class<T> getEntityClass() {
		return entityClass;
	}

	public T findById(ID id) {
		return entityManager.find(entityClass, id);
	}
	
	public T getReferenceById(ID id){
		return entityManager.getReference(entityClass, id);
	}
	
	@SuppressWarnings("unchecked")
	public List<T> findAll() {
		return entityManager.createQuery("from" + entityClass.getName()).getResultList();
	}

	@SuppressWarnings("unchecked")
	public List<T> findByExample(T exampleInstance, String... excludeProperty) {

		org.hibernate.Criteria crit = ((org.hibernate.ejb.HibernateEntityManager)entityManager)
        .getSession()
        .createCriteria(entityClass);
		
		org.hibernate.criterion.Example example =
            org.hibernate.criterion.Example.create(exampleInstance);
		
		for (String exclude : excludeProperty) {
			example.excludeProperty(exclude);
		}
		crit.add(example);
		
		return crit.list();
	}

	public T makePersistent(T entity) {
		return entityManager.merge(entity);
	}

	public void makeTransient(T entity) {
		entityManager.remove(entity);
	}

}
